<template>
  <a-layout class="layout-wrapper">
    <a-layout-header
      class="header"
      :style="{
        height: setPxValue(headerHeight),
        lineHeight: setPxValue(headerHeight)
      }"
    >
      <slot name="header"></slot>
    </a-layout-header>
    <a-layout>
      <a-layout-sider
        :collapsed-width="0"
        class="slider-left"
        theme="light"
        :width="leftWidth"
        v-model:collapsed="collapsedLeft"
      >
        <slot name="left"></slot>
        <div class="close-icon" @click="collapsedLeft = !collapsedLeft">
          <img v-if="collapsedLeft" src="@/assets/images/diy/slider-left-close.png" alt="" />
          <img v-else src="@/assets/images/diy/slider-left-open.png" alt="" />
        </div>
      </a-layout-sider>
      <a-layout-content ref="contentWrapperRef" class="content-wrapper">
        <div class="content">
          <vue3-ruler-tool
            :top="0"
            style="width: 100%; padding: 0"
            class="ruler-tool"
            :id="`ruler-tool_${store.showGrid}`"
            :visible="store.showGrid"
            :value="presetLine"
            :step-length="50"
            :parent="true"
            @input="input"
          >
            <div
              :style="{
                position: 'relative',
                ...dragZoneStyle
              }"
            >
              <div
                ref="previewZoneRef"
                class="preview-zone"
                :style="{
                  left: store.previewData.globalSetting.canvasX,
                  top: store.previewData.globalSetting.canvasY,
                  width: store.previewData.globalSetting.canvasWidth,
                  height: store.previewData.globalSetting.canvasHeight
                }"
              >
                <div :id="store.dragZoneId">
                  <slot name="main"></slot>
                </div>
              </div>
              <BaseControl
                ref="baseControlRef"
                :draggable="draggable"
                :resizable="resizeable"
                :keep-ratio="keepRatio"
                :target="previewZoneRef"
                @onSetStyle="emit('onSetCanvasStyle', $event)"
              ></BaseControl>
            </div>
          </vue3-ruler-tool>

          <div class="menu-list-wrapper">
            <a-switch
              class="margin-right-sm"
              v-model:checked="draggable"
              checked-children="drag"
              un-checked-children="drag"
            />
            <a-radio-group size="small" v-model:value="activeMenu">
              <a-tooltip v-for="(item, index) in menuList" :key="index" :title="item.label">
                <a-radio-button :value="item.value">
                  <img alt="" :src="item.icon" />
                </a-radio-button>
              </a-tooltip>
            </a-radio-group>
          </div>
        </div>
      </a-layout-content>

      <a-layout-sider
        :collapsed-width="0"
        class="slider-right"
        theme="light"
        :width="rightWidth"
        v-model:collapsed="collapsedRight"
      >
        <slot name="right"></slot>
        <div class="close-icon" @click="collapsedRight = !collapsedRight">
          <img v-if="collapsedRight" src="@/assets/images/diy/slider-left-close.png" alt="" />
          <img v-else src="@/assets/images/diy/slider-left-open.png" alt="" />
        </div>
      </a-layout-sider>
    </a-layout>
  </a-layout>
</template>
<script lang="ts" setup>
import { computed, nextTick, onMounted, type PropType, reactive, ref, watchEffect } from 'vue'
import { Vue3RulerTool } from 'vue3-ruler-tool'
import 'vue3-ruler-tool/dist/style.css'
import BaseControl from '@/components/BaseControl/index.vue'
import IconKeepRatioTrue from '@/assets/images/diy/keepRatio-true.png'
import IconKeepRatioFalse from '@/assets/images/diy/keepRatio-false.png'
import IconKeepNoResize from '@/assets/images/diy/no-resize.png'
import { debounce } from 'lodash-es'
import { useElementSize } from '@vueuse/core'
import { DiyStore } from '@/entity/DiyStore'
import { getPxValue, setPxValue } from '@/utils'

const props = defineProps({
  store: {
    type: Object as PropType<DiyStore>,
    required: true
  },
  headerHeight: {
    type: Number,
    default: 50
  },
  leftWidth: {
    type: Number,
    default: 250
  },
  rightWidth: {
    type: Number,
    default: 250
  }
})

const emit = defineEmits(['getGuidelines', 'onSetCanvasStyle', 'update:draggable'])
const collapsedLeft = ref<boolean>(false)
const collapsedRight = ref<boolean>(false)

watchEffect(() => {
  //处理全屏
  if (props.store?.isFullscreen) {
    collapsedLeft.value = true
    collapsedRight.value = true
  } else {
    collapsedLeft.value = false
    collapsedRight.value = false
  }
})

/**
 * 控制器
 */
const baseControlRef = ref()

const update = () => {
  nextTick(() => {
    baseControlRef.value?.update()
  })
}

const debounceUpdate = debounce(update, 200)

/**
 * 标尺
 */
const presetLine = ref([
  { type: 'h', site: 0 },
  { type: 'v', site: 0 }
])

//水平方向的辅助线
const horizontalGuidelines: any = computed(() => {
  const canvasY = getPxValue(props.store?.previewData.globalSetting.canvasY)
  return presetLine.value
    .filter((item) => item.type === 'h' && item.site > 0)
    .map((item) => {
      const value = +item.site - canvasY + 1
      return value > 0 ? value : 0
    })
})
//垂直方向的辅助线
const verticalGuidelines: any = computed(() => {
  const canvasX = getPxValue(props.store?.previewData.globalSetting.canvasX)
  return presetLine.value
    .filter((item) => item.type === 'v' && item.site > 0)
    .map((item) => {
      const value = +item.site - canvasX + 1
      return value > 0 ? value : 0
    })
})

const input = (list: any) => {
  presetLine.value = list
}

watchEffect(() => {
  const params = {
    horizontalGuidelines: horizontalGuidelines.value,
    verticalGuidelines: verticalGuidelines.value
  }
  emit('getGuidelines', params)
})

/**
 * 主区域
 */
const contentWrapperRef = ref()
const previewZoneRef = ref()

const dragZoneStyle = reactive<any>({
  width: 'auto',
  height: 'auto'
})

const { width, height } = useElementSize(contentWrapperRef)
const { width: previewZoneWidth, height: previewZoneHeight } = useElementSize(previewZoneRef)

watchEffect(() => {
  const gap = props.store?.showGrid ? 20 : 0
  if (width.value && height.value) {
    dragZoneStyle.width = setPxValue(width.value - gap)
    dragZoneStyle.height = setPxValue(height.value - gap)
    debounceUpdate()
  }

  if (previewZoneWidth.value && previewZoneHeight.value) {
    debounceUpdate()
  }
})
/**
 * 操作
 */

const draggable = ref(false)
const activeMenu = ref('KeepRatioTrue')

const keepRatio = computed(() => activeMenu.value === 'KeepRatioTrue')
const resizeable = computed(() => activeMenu.value !== 'NoResize')

const menuList = [
  {
    label: '按比例缩放',
    value: 'KeepRatioTrue',
    icon: IconKeepRatioTrue
  },
  {
    label: '任意比例缩放',
    value: 'KeepRatioFalse',
    icon: IconKeepRatioFalse
  },
  {
    label: '禁止缩放',
    value: 'NoResize',
    icon: IconKeepNoResize
  }
]
/**
 * 初始化
 */
onMounted(() => {
  props.store?.setCanvasControl(baseControlRef.value)
})

defineExpose({
  update,
  debounceUpdate
})
</script>

<style>
#ruler-tool_false .vue-ruler-content {
  padding: 0 !important;
}
</style>

<style lang="less" scoped>
:deep(.vue-ruler-v) {
  top: 0;
  background-color: #fff !important;
}

.layout-wrapper {
  height: 100vh;
  overflow: hidden;
  .header {
    position: sticky;
    top: 0;
    background-color: #fff;
    width: 100%;
    border-bottom: 1px solid #eef2f8;
    padding: 0;
  }

  .slider-left,
  .slider-right {
    position: relative;

    .close-icon {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      z-index: 1000;
      filter: drop-shadow(5px 5px 6px rgba(0, 0, 0, 0.04));
      img {
        width: 18px;
        height: 68px;
      }
    }
  }
  .slider-left .close-icon {
    right: -18px;
  }
  .slider-right .close-icon {
    left: -18px;
    transform: rotate(180deg);
    margin-top: -34px;
  }

  .content-wrapper {
    width: 100%;
    height: 100%;
    z-index: 999;
    background-color: #f1f1f1;
    position: relative;

    .grid {
      background-image: repeating-linear-gradient(#dedcdc 0 16px, transparent 0 32px),
        repeating-linear-gradient(90deg, #dedcdc 0 16px, transparent 0 32px);
      background-blend-mode: screen;
    }

    .content {
      width: 100%;
      height: 100%;
      position: relative;
    }

    .ruler-tool {
      width: 100%;
      height: 100%;
    }

    .preview-zone {
      background-color: #fff;
      position: absolute;
    }
  }
}

.menu-list-wrapper {
  position: absolute;
  bottom: 10px;
  right: 10px;
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;

  img {
    width: 18px;
    margin-bottom: 4px;
  }
}
</style>
